<?php

namespace mqtt;

use PhpMqtt\Client\ConnectionSettings;
use PhpMqtt\Client\MqttClient;
use think\exception\ValidateException;
use think\facade\Log;

class MQTTService
{
    protected MqttClient $client;
    protected array $config;

    public function __construct()
    {
        $this->config = config('mqtt');
        $this->connect();
    }

    protected function connect(): void
    {
        $host = $this->config['host'];
        $port = $this->config['port'];
        $clientId = $this->config['client_id'];
        $username = $this->config['username'] ?: null;
        $password = $this->config['password'] ?: null;
        $keepAlive = $this->config['keep_alive'];
        $scheme = $this->config['scheme'];

        // 创建 MQTT 客户端
        $this->client = new MqttClient($host, $port, $clientId);

        // 构建连接设置
        $settings = (new ConnectionSettings())
            ->setUsername($username)
            ->setPassword($password)
            ->setKeepAliveInterval($keepAlive)
            ->setUseTls($scheme === 'mqtts');

        if ($scheme === 'mqtts') {
            $settings = $settings->setTlsCertificateAuthorityFile($this->config['ssl_options']['cafile'] ?? null)
                ->setTlsVerifyPeer($this->config['ssl_options']['verify_peer'] ?? true);
        }

        // 连接
        try {
            $this->client->connect($settings, true);
            Log::record( "MQTT 连接成功");
        } catch (\Exception $e) {
            Log::record( "MQTT 连接失败: " . $e->getMessage() . "\n");
            throw new ValidateException($e->getMessage());
        }
    }

    /**
     * 发布消息
     * @param string $topic 主题
     * @param array $data 消息数据
     */
    public function publish(string $topic, array $data,bool $retain = false, int $qos = null): void
    {
        $qos = $qos ?? $this->config['qos'];
        $this->client->publish($topic, json_encode($data), $qos, $retain);
    }


    public function subscribe(string $topic, callable $callback, int $qos = null): void
    {
        $qos = $qos ?? $this->config['qos'];
        $this->client->subscribe($topic, $callback, $qos);
    }

    public function loop(): void
    {
        $this->client->loop();
    }

    public function disconnect(): void
    {
        $this->client->disconnect();
    }
}